﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using ch.ethz.ssh2.util;

namespace FormsTest
{
    public class TerminalWin
    {
        public TerminalWin(LoginMain loginMain, System.String title, ch.ethz.ssh2.Session sess, int term_width, int term_height)
        {
            this.loginMain = loginMain;
            this.sess = sess;
            this.term_width = term_width;
            this.term_height = term_height;
            input = sess.Stdout;
            output = sess.Stdin;
            System.Threading.Monitor.Enter(SyncRoot);
            InitializeComponent();
            new System.Threading.Thread(new System.Threading.ThreadStart(RemoteConsumer)).Start();
            new System.Threading.Thread(LocalConsumer).Start();
            System.Threading.Monitor.Wait(SyncRoot);
        }

        public void LocalConsumer()
        {
            try
            {
                while (true)
                {
                    ConsoleKeyInfo key = Console.ReadKey();
                    filterLenght++;
                    output.WriteByte(Convert.ToByte(key.KeyChar));
                    //string cmd = Console.ReadLine();
                    //filterLenght = cmd.Length;
                    //byte[] command = System.Text.Encoding.Default.GetBytes(cmd + "\n");
                    //foreach (byte b in command)
                    //{
                    //    output.WriteByte(b);
                    //}
                }
            }
            catch (Exception e) { }
        }

        public void RemoteConsumer()
        {
            System.Threading.Monitor.Enter(SyncRoot);
            byte[] buff = new byte[8192];

            try
            {
                while (handler(buff)) { }
            }
            catch (System.Exception e) { }
            finally
            {
                System.Threading.Monitor.PulseAll(SyncRoot);
                FreeConsole();
                Environment.Exit(0);
            }
        }

        private bool handler(byte[] data)
        {
            int len = (input is ch.ethz.ssh2.StreamGobbler || input is ch.ethz.ssh2.channel.ChannelInputStream) ? (int)Utility.InvokeMethodAsVirtual(input, "read", new System.Object[] { data }) : Utility.ReadInput(input, data, 0, data.Length);
            if (len == -1)
                return false;
            if (len >= 0)
            {
                string result = System.Text.Encoding.Default.GetString(data, 0, len);
                if (!string.IsNullOrEmpty(result))
                {
                    if (filterLenght > 0 && result.Length > filterLenght)
                    {
                        result = result.Substring(filterLenght);
                        filterLenght = 0;
                        Console.Write(result);
                    }
                    else if (filterLenght > 0 && result.Length <= filterLenght)
                    {
                        filterLenght = filterLenght - result.Length;
                    }
                    else
                    {
                        Console.Write(result);
                    }
                }
            }
            return true;
        }
        private int filterLenght = 0;

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            AllocConsole();
        }

        private LoginMain loginMain;
        internal System.IO.Stream input;
        internal System.IO.Stream output;
        private ch.ethz.ssh2.Session sess;
        private int term_width;
        private int term_height;
        private object SyncRoot = new object();

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool AllocConsole();

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool FreeConsole();

        [DllImport("kernel32", SetLastError = true)]
        static extern bool AttachConsole(int dwProcessId);

        [DllImport("user32.dll")]
        static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll", SetLastError = true)]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
    }
}
